use crate::connection::ConnectionManager;
use crate::error::Result;
use crate::handler::WebSocketHandler;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::{TcpListener};
use tracing::{error, info, warn};

pub struct WebSocketServer {
    connection_manager: Arc<ConnectionManager>,
    handler: Arc<WebSocketHandler>,
    addr: SocketAddr,
}

impl WebSocketServer {
    pub fn new(addr: SocketAddr) -> Self {
        let connection_manager = Arc::new(ConnectionManager::new());
        let handler = Arc::new(WebSocketHandler::new(Arc::clone(&connection_manager)));
        
        Self {
            connection_manager,
            handler,
            addr,
        }
    }
    
    pub async fn run(&self) -> Result<()> {
        info!("Starting WebSocket server on {}", self.addr);
        
        let listener = TcpListener::bind(self.addr).await?;
        info!("WebSocket server listening on {}", self.addr);
        
        // Start statistics reporting task
        self.start_stats_reporter();
        
        // Start connection cleanup task
        self.start_connection_cleanup();
        
        loop {
            match listener.accept().await {
                Ok((stream, addr)) => {
                    info!("New connection attempt from: {}", addr);
                    
                    let handler = Arc::clone(&self.handler);
                    
                    // Spawn a new task to handle the connection
                    tokio::spawn(async move {
                        if let Err(e) = handler.handle_connection(stream, addr).await {
                            error!("Error handling connection from {}: {}", addr, e);
                        }
                    });
                }
                Err(e) => {
                    error!("Failed to accept connection: {}", e);
                    // Continue accepting connections even if one fails
                    continue;
                }
            }
        }
    }
    
    fn start_stats_reporter(&self) {
        let stats = self.connection_manager.get_stats();
        
        tokio::spawn(async move {
            let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(30));
            
            loop {
                interval.tick().await;
                
                let total = stats.total_connections.load(std::sync::atomic::Ordering::Relaxed);
                let active = stats.active_connections.load(std::sync::atomic::Ordering::Relaxed);
                let sent = stats.messages_sent.load(std::sync::atomic::Ordering::Relaxed);
                let received = stats.messages_received.load(std::sync::atomic::Ordering::Relaxed);
                
                info!(
                    "Server Stats - Total: {}, Active: {}, Messages Sent: {}, Messages Received: {}",
                    total, active, sent, received
                );
            }
        });
    }
    
    fn start_connection_cleanup(&self) {
        let connection_manager = Arc::clone(&self.connection_manager);
        
        tokio::spawn(async move {
            let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(60));
            
            loop {
                interval.tick().await;
                
                let connections = connection_manager.get_all_connections();
                let now = current_timestamp();
                let timeout_duration = 300; // 5 minutes
                
                let mut inactive_count = 0;
                
                for conn_info in connections {
                    let last_activity = conn_info.last_activity;
                    if now - last_activity > timeout_duration {
                        if connection_manager.remove_connection(&conn_info.id).is_some() {
                            inactive_count += 1;
                        }
                    }
                }
                
                if inactive_count > 0 {
                    warn!("Cleaned up {} inactive connections", inactive_count);
                }
            }
        });
    }
    
    pub fn get_connection_manager(&self) -> Arc<ConnectionManager> {
        Arc::clone(&self.connection_manager)
    }
}

fn current_timestamp() -> u64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_secs()
}